// -*-mode:c++; coding:utf-8-*-

#include "logger.hpp"

#include "table_info_cache.hpp"

namespace xbase
{
	void table_info_cache::on_get_table_info_response(std::string table_name,
		protocol::packet_ptr pkt_ptr,
		const error_code &ec)
	{
		table_info_ptr tmp_ptr;
		handler_list list;
		response_packet_type *p = NULL;

		boost::system::error_code e = ec;
		if (! e)
		{
			if(pkt_ptr->get_type() != response_packet_type::type)
			{
				e = error::bad_packet_type;
			}
			else
			{
				p = boost::polymorphic_downcast<response_packet_type*>(pkt_ptr.get());
				if (p->body().error_code())
				{
					e = p->body().error_code();
				}
				else
				{
					if (p->body().m_table_info.m_table_name != table_name)
					{
						e = error::table_name_mismatch;
					}
				}
			}
		}

		boost::mutex::scoped_lock lock(m_mutex);
		const protocol::table_info_response &resp = p->body();
		if(! e)
		{
			/*
			* 因为异步返回以后，有可能有新的更新根子表位置的请求，这时原来获得的根子表信息读写有可能会冲突，
			* 所以当要更新时，不改变原来可能已经返回的指针，而使用新建的指针
			*/

			tmp_ptr = table_info_ptr(new protocol::table_info);
			*tmp_ptr = resp.m_table_info;

			m_table_info_map[table_name] = tmp_ptr;
		}

		const handler_map::iterator iter = m_request_map.find(table_name);
		if (iter != m_request_map.end())
		{
			list.swap(iter->second);
			m_request_map.erase(iter);
		}

		lock.unlock();

		LOG_IF(e, DEBUG,
			"table_info_cache<>::on_get_table_info_response error occur: "
			<< e << " - " << e.message());

		while (!list.empty())
		{
			this->get_upper_level_service().dispatch(boost::bind(list.front(), tmp_ptr, ec));
			list.pop_front();
		}
	}

	void table_info_cache::async_get_table_info(const std::string &table_name, handler_type handler, bool hard)
	{
		error_code ec;

		boost::mutex::scoped_lock lock(m_mutex);

		table_info_map::iterator iter = m_table_info_map.find(table_name);

		if (!hard && (iter != m_table_info_map.end()))
		{
			this->get_upper_level_service().dispatch(boost::bind(handler, iter->second, ec));
		}
		else
		{
			handler_list &list = m_request_map[table_name];
			bool is_requested = (!list.empty());
			list.push_back(handler);

			lock.unlock();

			if (!is_requested)
			{
				// 异步获得根子表信息
				request_packet_ptr pkt_ptr(new request_packet_type());
				pkt_ptr->body().m_table_name = table_name;

				xbase::async_write(m_session_manager, m_master_server_endpoint, pkt_ptr,
					boost::bind(&this_type::on_get_table_info_response,
					this_ptr(), table_name,
					_1, _2));
			}
		}
	}
}
